#include "stdafx.h"
#include "XCheckBoxImpl.h"

#include <Util.h>
#include <UIUtil.h>
#include "DrawUtil.h"
#include <IntSkinImpl.h>

//////////////////////////////////////////////////////////////////////////

static const int g_CheckImageTextInternal = 5;



//////////////////////////////////////////////////////////////////////////

template <class I>
CXCheckBoxImpl<I>::CXCheckBoxImpl()
{
    m_ChkState = CBS_UnChecked;
}

template <class I>
CXCheckBoxImpl<I>::~CXCheckBoxImpl()
{
}

//////////////////////////////////////////////////////////////////////////
// IXCheckBox
template <class I>
void CXCheckBoxImpl<I>::put_Check(IN CheckBoxState eCheckState)
{
    if(eCheckState != m_ChkState)
    {
        m_ChkState = eCheckState;

        if(m_ChkState == CBS_UnChecked && !m_strUnCheckText.empty())
        {
            m_strOrgText = m_strText;
            put_Text(m_strUnCheckText);
        }
        else if(!m_strOrgText.empty())
        {
            put_Text(m_strOrgText);
            m_strOrgText = _T("");
        }

        if(m_pButtonDraw != NULL)
        {
            int nHorzIndex, nVertIndex;
            m_pButtonDraw->get_Index(&nHorzIndex, &nVertIndex);
            m_pButtonDraw->put_Index(nHorzIndex, (int)m_ChkState);
        }

        Invalidate();
    }
}

template <class I>
CheckBoxState CXCheckBoxImpl<I>::get_Check()
{
    return m_ChkState;
}

template <class I>
HRESULT CXCheckBoxImpl<I>::put_UnCheckText(IN LPCTSTR szUnCheckText)
{
    if(m_strUnCheckText != szUnCheckText)
    {
        IntSkinImpl::SetorLoadStringSaveResId(szUnCheckText, m_strUnCheckText, m_strUnCheckTextResId);
        if(m_ChkState == CBS_UnChecked)
        {
            put_Text(m_strUnCheckText);
        }
    }
    return S_OK;
}

template <class I>
HRESULT CXCheckBoxImpl<I>::get_UnCheckText(IN BSTR* pbstrUnCheckText)
{
    return (::SysReAllocString(pbstrUnCheckText, m_strUnCheckText.GetData()) != FALSE) ? S_OK : E_FAIL;
}

//////////////////////////////////////////////////////////////////////////
// IXFrame
template <class I>
void CXCheckBoxImpl<I>::GetAutoSize(OUT LPSIZE pAutoSize)
{
    SIZE sizeImage = *pAutoSize;
    NeedImage();
    if(m_pButtonDraw == NULL)
    {
        superclass::GetAutoSize(&sizeImage);
    }
    else
    {
        m_pButtonDraw->get_ImageSize(&sizeImage);
    }

    SIZE sizeText = {0};
    if(!m_strText.empty())
    {
        CXFrameImpl<I>::GetAutoSize(&sizeText);
        sizeText.cx += 4;
        sizeText.cy += 4;
    }

    pAutoSize->cx = sizeImage.cx + sizeText.cx + ((sizeText.cx > 0) ? g_CheckImageTextInternal : 0);
    pAutoSize->cy = max(sizeImage.cy, sizeText.cy);
}

template <class I>
void CXCheckBoxImpl<I>::Draw(XCANVAS xCanvas, const RECT& rcDraw)
{
    CXFrameImpl<I>::Draw(xCanvas, rcDraw);

    RECT rcWnd;
    get_WindowRect(&rcWnd);

    HRESULT hResult = S_OK;

    NeedImage();
    if(m_pButtonDraw != NULL)
    {
        SIZE sizeImage;
        m_pButtonDraw->get_ImageSize(&sizeImage);

        RECT rcImage = rcWnd;
        rcImage.right = rcImage.left + sizeImage.cx;
        rcImage.bottom = rcImage.top + sizeImage.cy;

        if((rcWnd.bottom - rcWnd.top) > sizeImage.cy)
        {
            int nOffsetVert = ((rcWnd.bottom - rcWnd.top) - sizeImage.cy) / 2;
            ::OffsetRect(&rcImage, 0, nOffsetVert);
        }
        else
        {
            rcImage.bottom = rcWnd.bottom;
            if(sizeImage.cy != 0)
                rcImage.right =  rcImage.left + (rcImage.bottom - rcImage.top) * sizeImage.cx / sizeImage.cy;
        }

//         if(TestControlFlags(ESkin_Down))
//             ::OffsetRect(&rcImage, 1, 1);

        if(sizeImage.cy != 0)
            hResult = m_pButtonDraw->Draw(xCanvas, &rcImage);
        rcWnd.left += (g_CheckImageTextInternal + sizeImage.cx);
    }

    if(!m_strText.empty())
    {
        IXFont* pFont = NULL;
        IXTextEnv* pTextEnv = NULL;

        get_Font(&pFont);
        get_TextEnv(&pTextEnv);

//         if(TestControlFlags(ESkin_Down))
//             ::OffsetRect(&rcWnd, 1, 1);

        DrawUtil::XDrawText(xCanvas, m_strText, m_strText.Length(), &rcWnd, pTextEnv, pFont);
    }
}

//////////////////////////////////////////////////////////////////////////
// IXBaseObj
template <class I>
void CXCheckBoxImpl<I>::OnConstruct()
{
    superclass::OnConstruct();
    IXTextEnv* pTextEnv = UIUtil::XGetTextEnv(this);
    DWORD dwFlags = pTextEnv->get_DrawFlags();
    pTextEnv->put_DrawFlags(dwFlags & (~DT_CENTER));
}

template <class I>
void CXCheckBoxImpl<I>::OnFinalRelease()
{
    superclass::OnFinalRelease();
}

//////////////////////////////////////////////////////////////////////////
// CXCheckBoxImpl
template <class I>
void CXCheckBoxImpl<I>::ReleaseData()
{
    ;
}

template <class I>
void CXCheckBoxImpl<I>::NeedImage()
{
    if(m_pButtonDraw == NULL)
    {
        if(SUCCEEDED(Util::CreateObject(&m_pButtonDraw)))
        {
            m_pButtonDraw->put_ImagePath(_T("@skin:Common\\checkbutton.png"));
            m_pButtonDraw->put_SubCount(4, 3);
        }
    }
}

template <class I>
void CXCheckBoxImpl<I>::OnImageChanged()
{
    if(m_pButtonDraw != NULL)
    {
        int nHorzIndex, nVertIndex;
        m_pButtonDraw->get_Index(&nHorzIndex, &nVertIndex);
        m_pButtonDraw->put_Index(nHorzIndex, (int)m_ChkState);
    }
}

// CXFrameImpl
template <class I>
BOOL CXCheckBoxImpl<I>::OnClicked(const POINT* pt)
{
    CheckBoxState state = (m_ChkState == CBS_Indeterminate) ? CBS_Checked : ((m_ChkState == CBS_Checked) ? CBS_UnChecked : CBS_Checked);

    put_Check(state);

    superclass::OnClicked(pt);
    return TRUE;
}

// CXControlImpl
template <class I>
HRESULT CXCheckBoxImpl<I>::OnSkinLangChanged()
{
    superclass::OnSkinLangChanged();

    XString strUnCheckText;
    XString strUnCheckTextResId = m_strUnCheckTextResId;
    if(IntSkinImpl::ReLoadString(strUnCheckTextResId.c_str(), strUnCheckText))
    {
        put_UnCheckText(strUnCheckText.c_str());
        m_strUnCheckTextResId = strUnCheckTextResId;
    }
    return S_OK;
}